<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class WechatVerifyController extends Controller
{
    /**
     * 微信服务器验证
     * 用于验证微信公众号的服务器配置
     */
    public function verify(Request $request)
    {
        $signature = $request->get('signature');
        $timestamp = $request->get('timestamp');
        $nonce = $request->get('nonce');
        $echostr = $request->get('echostr');
        
        Log::info('微信服务器验证请求', [
            'signature' => $signature,
            'timestamp' => $timestamp,
            'nonce' => $nonce,
            'echostr' => $echostr,
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent()
        ]);
        
        // 验证签名
        if ($this->checkSignature($signature, $timestamp, $nonce)) {
            Log::info('微信服务器验证成功');
            return response($echostr);
        } else {
            Log::warning('微信服务器验证失败');
            return response('验证失败', 403);
        }
    }
    
    /**
     * 检查微信签名
     */
    private function checkSignature($signature, $timestamp, $nonce)
    {
        $token = config('wechat.token');
        
        // 将token、timestamp、nonce三个参数进行字典序排序
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        
        // 将三个参数字符串拼接成一个字符串进行sha1加密
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        
        // 将加密后的字符串与signature进行对比
        return $tmpStr === $signature;
    }
    
    /**
     * 处理微信消息
     */
    public function handleMessage(Request $request)
    {
        $signature = $request->get('signature');
        $timestamp = $request->get('timestamp');
        $nonce = $request->get('nonce');
        
        // 验证签名
        if (!$this->checkSignature($signature, $timestamp, $nonce)) {
            Log::warning('微信消息签名验证失败');
            return response('签名验证失败', 403);
        }
        
        // 获取微信消息内容
        $postStr = $request->getContent();
        
        Log::info('收到微信消息', [
            'post_data' => $postStr,
            'signature' => $signature,
            'timestamp' => $timestamp,
            'nonce' => $nonce
        ]);
        
        // 解析XML消息
        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        
        if ($postObj === false) {
            Log::error('解析微信消息XML失败', [
                'post_data' => $postStr
            ]);
            return response('XML解析失败', 400);
        }
        
        // 处理不同类型的消息
        $msgType = (string)$postObj->MsgType;
        
        switch ($msgType) {
            case 'text':
                return $this->handleTextMessage($postObj);
            case 'event':
                return $this->handleEventMessage($postObj);
            default:
                Log::info('收到未处理的消息类型', [
                    'msg_type' => $msgType,
                    'post_data' => $postStr
                ]);
                return response('success');
        }
    }
    
    /**
     * 处理文本消息
     */
    private function handleTextMessage($postObj)
    {
        $fromUser = (string)$postObj->FromUserName;
        $toUser = (string)$postObj->ToUserName;
        $content = (string)$postObj->Content;
        
        Log::info('处理文本消息', [
            'from_user' => $fromUser,
            'to_user' => $toUser,
            'content' => $content
        ]);
        
        // 这里可以添加自动回复逻辑
        $replyContent = "感谢您的消息：" . $content;
        
        return $this->replyTextMessage($fromUser, $toUser, $replyContent);
    }
    
    /**
     * 处理事件消息
     */
    private function handleEventMessage($postObj)
    {
        $fromUser = (string)$postObj->FromUserName;
        $toUser = (string)$postObj->ToUserName;
        $event = (string)$postObj->Event;
        
        Log::info('处理事件消息', [
            'from_user' => $fromUser,
            'to_user' => $toUser,
            'event' => $event
        ]);
        
        switch ($event) {
            case 'subscribe':
                return $this->handleSubscribeEvent($fromUser, $toUser);
            case 'unsubscribe':
                return $this->handleUnsubscribeEvent($fromUser, $toUser);
            case 'CLICK':
                return $this->handleClickEvent($postObj);
            default:
                return response('success');
        }
    }
    
    /**
     * 处理关注事件
     */
    private function handleSubscribeEvent($fromUser, $toUser)
    {
        Log::info('用户关注', [
            'from_user' => $fromUser,
            'to_user' => $toUser
        ]);
        
        $replyContent = "欢迎关注换换猫商城！\n\n我们提供专业的宠物用品服务，包括：\n• 优质宠物用品\n• 商家入驻服务\n• 同城配送\n\n点击下方菜单开始体验吧！";
        
        return $this->replyTextMessage($fromUser, $toUser, $replyContent);
    }
    
    /**
     * 处理取消关注事件
     */
    private function handleUnsubscribeEvent($fromUser, $toUser)
    {
        Log::info('用户取消关注', [
            'from_user' => $fromUser,
            'to_user' => $toUser
        ]);
        
        return response('success');
    }
    
    /**
     * 处理点击事件
     */
    private function handleClickEvent($postObj)
    {
        $fromUser = (string)$postObj->FromUserName;
        $toUser = (string)$postObj->ToUserName;
        $eventKey = (string)$postObj->EventKey;
        
        Log::info('处理点击事件', [
            'from_user' => $fromUser,
            'to_user' => $toUser,
            'event_key' => $eventKey
        ]);
        
        return response('success');
    }
    
    /**
     * 获取微信JS-SDK签名
     * 用于前端微信JS-SDK配置
     * 只需要 app_id 和 app_secret
     */
    public function getJsSdkSignature(Request $request)
    {
        try {
            $url = $request->get('url');
            
            if (empty($url)) {
                return response()->json([
                    'result' => 0,
                    'msg' => 'URL参数不能为空'
                ], 400);
            }
            
            // 从 wechat.php 配置文件中获取微信配置
            $appId = config('wechat.app_id');
            $appSecret = config('wechat.app_secret');
            
            Log::info('开始获取微信JS-SDK签名', [
                'app_id' => $appId,
                'url' => $url,
                'config_source' => 'wechat.php'
            ]);
            
            if (empty($appId) || empty($appSecret)) {
                Log::error('微信配置不完整', [
                    'app_id' => $appId,
                    'app_secret' => $appSecret ? '已配置' : '未配置'
                ]);
                
                return response()->json([
                    'result' => 0,
                    'msg' => '微信配置不完整，请检查 wechat.php 配置文件'
                ], 500);
            }
            
            // 1. 获取access_token
            $accessToken = $this->getAccessToken($appId, $appSecret);
            if (!$accessToken) {
                return response()->json([
                    'result' => 0,
                    'msg' => '获取access_token失败'
                ], 500);
            }
            
            // 2. 获取jsapi_ticket
            $jsapiTicket = $this->getJsapiTicket($accessToken);
            if (!$jsapiTicket) {
                return response()->json([
                    'result' => 0,
                    'msg' => '获取jsapi_ticket失败'
                ], 500);
            }
            
            // 3. 生成签名参数
            $timestamp = time();
            $nonceStr = $this->generateNonceStr();
            
            // 4. 生成签名
            $signature = $this->generateSignature($jsapiTicket, $nonceStr, $timestamp, $url);
            
            Log::info('微信JS-SDK签名生成成功', [
                'app_id' => $appId,
                'url' => $url,
                'timestamp' => $timestamp,
                'nonceStr' => $nonceStr,
                'signature' => $signature
            ]);
            
            return response()->json([
                'result' => 1,
                'msg' => '获取成功',
                'data' => [
                    'appId' => $appId,
                    'timestamp' => $timestamp,
                    'nonceStr' => $nonceStr,
                    'signature' => $signature
                ]
            ]);
            
        } catch (\Exception $e) {
            Log::error('获取微信JS-SDK签名失败', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'url' => $request->get('url')
            ]);
            
            return response()->json([
                'result' => 0,
                'msg' => '获取签名失败：' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * 获取微信access_token
     */
    private function getAccessToken($appId, $appSecret)
    {
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
        
        Log::info('开始获取微信access_token', [
            'app_id' => $appId,
            'url' => $url
        ]);
        
        $response = $this->httpGet($url);
        
        if ($response === false) {
            Log::error('HTTP请求失败，无法获取access_token');
            return false;
        }
        
        $data = json_decode($response, true);
        
        Log::info('微信API响应', [
            'response' => $response,
            'parsed_data' => $data
        ]);
        
        if (isset($data['access_token'])) {
            Log::info('成功获取access_token', [
                'access_token' => substr($data['access_token'], 0, 10) . '...'
            ]);
            return $data['access_token'];
        }
        
        Log::error('获取access_token失败', [
            'response' => $response,
            'parsed_data' => $data,
            'app_id' => $appId,
            'error_code' => $data['errcode'] ?? 'unknown',
            'error_msg' => $data['errmsg'] ?? 'unknown'
        ]);
        
        return false;
    }
    
    /**
     * 获取微信jsapi_ticket
     */
    private function getJsapiTicket($accessToken)
    {
        $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi";
        
        $response = $this->httpGet($url);
        $data = json_decode($response, true);
        
        if (isset($data['ticket'])) {
            return $data['ticket'];
        }
        
        Log::error('获取jsapi_ticket失败', [
            'response' => $response,
            'access_token' => $accessToken
        ]);
        
        return false;
    }
    
    /**
     * 生成随机字符串
     */
    private function generateNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    
    /**
     * 生成微信JS-SDK签名
     */
    private function generateSignature($jsapiTicket, $nonceStr, $timestamp, $url)
    {
        // 按字典序排列参数
        $params = [
            'jsapi_ticket' => $jsapiTicket,
            'noncestr' => $nonceStr,
            'timestamp' => $timestamp,
            'url' => $url
        ];
        
        ksort($params);
        
        // 拼接字符串
        $string1 = '';
        foreach ($params as $key => $value) {
            $string1 .= $key . '=' . $value . '&';
        }
        $string1 = rtrim($string1, '&');
        
        // SHA1加密
        $signature = sha1($string1);
        
        return $signature;
    }
    
    /**
     * HTTP GET请求
     */
    private function httpGet($url)
    {
        Log::info('发起HTTP GET请求', [
            'url' => $url
        ]);
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        $curlErrno = curl_errno($ch);
        
        curl_close($ch);
        
        Log::info('HTTP请求完成', [
            'url' => $url,
            'http_code' => $httpCode,
            'curl_errno' => $curlErrno,
            'curl_error' => $curlError,
            'response_length' => strlen($response)
        ]);
        
        if ($curlErrno) {
            Log::error('HTTP请求失败', [
                'error' => $curlError,
                'errno' => $curlErrno,
                'url' => $url
            ]);
            return false;
        }
        
        if ($httpCode !== 200) {
            Log::error('HTTP请求返回错误状态码', [
                'http_code' => $httpCode,
                'url' => $url,
                'response' => $response
            ]);
            return false;
        }
        
        return $response;
    }

    /**
     * 回复文本消息
     */
    private function replyTextMessage($fromUser, $toUser, $content)
    {
        $replyXml = "<xml>
            <ToUserName><![CDATA[{$fromUser}]]></ToUserName>
            <FromUserName><![CDATA[{$toUser}]]></FromUserName>
            <CreateTime>" . time() . "</CreateTime>
            <MsgType><![CDATA[text]]></MsgType>
            <Content><![CDATA[{$content}]]></Content>
        </xml>";
        
        return response($replyXml, 200, [
            'Content-Type' => 'application/xml'
        ]);
    }
}
